﻿//#define START_AND_READ_BY_BARCODE  //由条码来启动和读取数据

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using Kuge.AppSetting;
using System.Xml;
using System.Xml.Linq;//需要引用System.Xml.Linq.dll

namespace QMS
{
    public partial class frmMain : Form
    {
        private const int CHANNEL_MAX = 2;
        private const string INI_PASSWORD = "$ABCDEFGH$";

        private readonly Rectangle Screen;

        private Kuge.Controls.AutoLabel lblInfo;

        private int SelectedChannel = 1;

        private readonly string Title;

        #region frmMain

        public frmMain()
        {
            InitializeComponent();

            this.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);
            Title = this.Text;

            Screen = System.Windows.Forms.SystemInformation.WorkingArea;

            this.StartPosition = FormStartPosition.Manual;
            this.Top = Screen.Height - this.Height - 20;
            this.Left = Screen.Width - this.Width - 20;
            this.TopMost = true;

            Kuge.Message.Online = true;
            Kuge.Message.MainForm = this;
            lblInfo = new Kuge.Controls.AutoLabel();
            lblInfo.Dock = DockStyle.Fill;
            pnlInfo.Controls.Add(lblInfo);

            INI.SetFileName(Path.ChangeExtension(Application.ExecutablePath, ".ini"));
            INI.Password = INI_PASSWORD;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            StringBuilder Items = new StringBuilder();

            #region ItemDictionary初始化

#if false
            string AliasDatFile = Path.Combine(Application.StartupPath, "Alias.dat");
            ItemDictionary.Clear();
            if (File.Exists(AliasDatFile))
            {

                XmlDocument xml = new XmlDocument();
                xml.Load(AliasDatFile);

                Items.Append("请确认项目上传的名称:\r\n");

                foreach (XmlNode node in xml.DocumentElement.ChildNodes)
                {
                    if (ItemDictionary.ContainsKey(node.Name) == false)
                    {
                        try
                        {
                            XmlNode subNode = node.SelectSingleNode("@Including");
                            if ((subNode != null) && (subNode.Value.ToLower() == "true"))
                            {
                                ItemDictionary.Add(node.Name, node.InnerText);
                                Items.AppendFormat("{0}\r\n", node.InnerText);
                            }
                        }
                        catch
                        {
                        }
                    }
                }
            }
            else
            {
                Kuge.Message.PopupErrorText("找不到Alias.dat文件", this, 60000, "");
            } 
#endif

            #endregion

            #region ReadThread

            Testpad.BTS.MemoryMapped.QueueEnable = false;//不使用队列

#if !START_AND_READ_BY_BARCODE
            for (int Channel = 1; Channel <= CHANNEL_MAX; Channel++)
            {
                Thread ReadThread = new Thread(new ParameterizedThreadStart(Reading));
                ReadThread.IsBackground = true;//后台线程，软件关闭时自动销毁，没毛病
                ReadThread.Name = string.Format("ReadThread {0}", Channel);//线程名字，可省
                ReadThread.Start(Channel);
            }
#endif

            #endregion

            //打开刷新定时器
            T_Status.Enabled = true;

            //INI.Set("Sorter", "URL", "http://172.30.201.52:8889/QmsService.asmx");
            INI.Get("Sorter", this.Controls);

            ClearLog(Items.ToString());
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;

            txtBarcode.Clear();

            INI.Set("Sorter", this.Controls);

            e.Cancel = false;
        }

        #endregion

        #region ItemDictionary

        /// <summary>
        /// 用于映射简码和数据名称的字典
        /// </summary>
        private Dictionary<string, string> ItemDictionary = new Dictionary<string, string>();

        /// <summary>
        /// 从字典中查找简码对应的名称
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private string GetItemName(string key)
        {
            if (ItemDictionary.ContainsKey(key))
            {
                return ItemDictionary[key];
            }
            return key;
        }

        #endregion

        #region Lable

        public void TipsOn(bool isError, string text, UInt32 delay = 0)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<bool, string, UInt32>(TipsOn), isError, text, delay);
            }
            else
            {
                lblInfo.TipsOn(isError, text, delay);
            }
        }

        public void TipsOff()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(TipsOff));
            }
            else
            {
                lblInfo.TipsOff();
            }
        }

        #endregion

        #region Display

        private void Display(TextBox txt, string Content)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<TextBox, string>(Display), txt, Content);
            }
            else
            {
                txt.Text = Content;
            }
        }

        #endregion

        #region Log

        private void ClearLog(string Content)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(ClearLog), Content);
            }
            else
            {
                //txtOutput.Clear();
                //txtOutput.AppendText($"{Content}\r\n");
            }
        }

        private void AppendLog( string Content)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(AppendLog), Content);
            }
            else
            {
                //txtOutput.AppendText($"{Content}\r\n");
            }
        }

        #endregion

        #region Timer

        private void T_Status_Tick(object sender, EventArgs e)
        {
            bool IsRunning;

            //指示BTS.EXE是否正在运行
            IsRunning = Testpad.BTS.MemoryMapped.BTS_IsRunning;
            if (IsRunning)
            {
                this.Text = $"{Title}(BTS运行中...)";
            }
            else
            {
                this.Text = $"{Title}QMS(BTS未运行)";
            }
        }

        #endregion

        #region START_AND_READ_BY_BARCODE

#if START_AND_READ_BY_BARCODE

        private void BeginRead(int Channel, int Timeout)
        {
            IAsyncResult IAsync;
            Action<int, int> Op = new Action<int, int>(EndRead);
            IAsync = Op.BeginInvoke(Channel, Timeout, null, null);
        }

        private void EndRead(int Channel, int Timeout)
        {
            List<Testpad.BTS.DataListItem> DataList;
            bool DataIsReady = Testpad.BTS.MemoryMapped.Pick(Channel, Timeout, out DataList);
            if ((DataIsReady) && (DataList != null))
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("数据更新于:{0:yyyy/MM/dd HH:mm:ss}\r\n", DateTime.Now);
                foreach (var v in DataList)
                {
                    // string DataName = v.Name;
                    //可以调用DataName=GetItemName(v.Key)转换成自定义名称,也可使用默认名称
                    string DataName = GetItemName(v.Key);
                    sb.AppendFormat("项目[{0}]:{1},值:{2},标志:{3}\r\n", v.Key, DataName, v.Value, v.Flag);
                }

                switch (Channel)
                {
                    case 1:
                        {
                            Display(txtChannel1, sb.ToString());
                            break;
                        }
                    case 2:
                        {
                            Display(txtChannel2, sb.ToString());
                            break;
                        }
                }
            }
            else
            {
                switch (Channel)
                {
                    case 1:
                        {
                            Display(txtChannel1, "Timeout");
                            break;
                        }
                    case 2:
                        {
                            Display(txtChannel2, "Timeout");
                            break;
                        }
                }
            }
        }

#endif 

        #endregion

        #region ReadThread
        
        #if !START_AND_READ_BY_BARCODE
        private void Reading(object n)
        {
            int? Channel = n as int?;
            if(Channel!=null)
            {
                List<Testpad.BTS.DataListItem> DataList;
                while (true)
                {
                    #region 自动读回所有通道数据

                    bool DataIsReady = Testpad.BTS.MemoryMapped.Pick((int)Channel, 30000, out DataList);
                    if ((DataIsReady) && (DataList != null))
                    {
                        string Barcode = string.Empty;

                        lblInfo.TipsOff();

                        foreach (var v in DataList)
                        {
                            if(v.Key == "D00")
                            {
                                double Voltage;
                                if(double.TryParse(v.Value,out Voltage))
                                {
                                    if((Voltage > (double)numD_Max.Value) || (Voltage < (double)numA_Min.Value))
                                    {
                                        Kuge.Message.PopupError("不属于A/B/C/D中的任何一组!", this);
                                        lblInfo.TipsOn(true, "不属于A/B/C/D中的任何一组!", 30000);
                                    }
                                    else if (Voltage > (double)numD_Min.Value)
                                    {
                                        Kuge.Message.PopupZoomInMessage("D", this, 30000);
                                        lblInfo.TipsOn(false, "D", 30000);
                                    }
                                    else if (Voltage > (double)numC_Min.Value)
                                    {
                                        Kuge.Message.PopupZoomInMessage("C", this, 30000);
                                        lblInfo.TipsOn(false, "C", 30000);
                                    }
                                    else if (Voltage > (double)numB_Min.Value)
                                    {
                                        Kuge.Message.PopupZoomInMessage("B", this, 30000);
                                        lblInfo.TipsOn(false, "B", 30000);
                                    }
                                    else if (Voltage > (double)numA_Min.Value)
                                    {
                                        Kuge.Message.PopupZoomInMessage("A", this, 30000);
                                        lblInfo.TipsOn(false, "A", 30000);
                                    }
                                }
                                else
                                {
                                    Kuge.Message.PopupErrorText("数据无效!", this);
                                }
                                break;
                            }
                        }
                    }

                    #endregion

                    Thread.Sleep(1);
                }
            }
        }
        #endif

        #endregion

        #region Send Barcode

        private void txtBarcode_KeyPress(object sender, KeyPressEventArgs e)
        {
            T_AutoFocus.Enabled = false;
            if ((int)e.KeyChar == 13)
            {
                lblInfo.TipsOn(false, txtBarcode.Text);
                Kuge.Message.PopupMessageOff(this);
                ClearLog(txtBarcode.Text);
                Testpad.BTS.MemoryMapped.SendBarcode(SelectedChannel, txtBarcode.Text);
                txtBarcode.Clear();
            }
            T_AutoFocus.Enabled = true;
        }

        private void T_AutoFocus_Tick(object sender, EventArgs e)
        {
            txtBarcode.Focus();
            txtBarcode.SelectAll();
        }

        private void txtBarcode_MouseClick(object sender, MouseEventArgs e)
        {
            T_AutoFocus.Enabled = true;
        }

        private void txt_TextChanged(object sender, EventArgs e)
        {
            T_AutoFocus.Enabled = false;
        }

        #endregion

        #region Send Parameter

        private void btnSendParameter_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "*.xml|*.xml";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                FileInfo fInfo = new FileInfo(dlg.FileName);
                using (StreamReader sr = fInfo.OpenText())
                {
                    string content = sr.ReadToEnd();
                    if (string.IsNullOrEmpty(content) == false)
                    {
                        Testpad.BTS.MemoryMapped.SendParameter(content);
                    }
                }
            }
        }






        #endregion
    }
}
